<template>
  <div class="china-map-3d-container">
    <!-- 返回按钮 -->
    <button class="back-button" @click="goBack">
      <span class="back-icon">←</span>
      <span class="back-text">返回</span>
    </button>
    
    <!-- 标题 -->
    <div class="title-section">
      <h1 class="main-title">树岛3D实时信息传输</h1>
      <p class="sub-title">高级交互式三维可视化</p>
    </div>
    
    <div ref="map2dRef" class="map-2d-layer" />
    <div ref="mapRef" class="map-3d-layer" />
    <div
      ref="toolTipRef"
      class="tooltip"
      :class="{ visible: toolTipData.visible }"
      :style="{
        left: toolTipData.x + 'px',
        top: toolTipData.y + 'px'
      }"
    >
      {{ toolTipData.text || '未知区域' }}
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch, reactive } from 'vue'
import { useRouter } from 'vue-router'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
import { Line2 } from 'three/examples/jsm/lines/Line2'
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry'
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial'
import * as d3 from 'd3'
import gsap from 'gsap'
import * as dat from 'dat.gui'
import axios from 'axios'

// 类型定义
interface GeoJsonType {
  type: 'FeatureCollection'
  features: GeoJsonFeature[]
}

interface GeoJsonFeature {
  type: string
  properties: {
    adcode: number
    name: string
    center: [number, number]
    centroid: [number, number]
    childrenNum: number
    level: 'province' | 'city' | 'district'
    parent: { adcode: number }
    subFeatureIndex: number
    acroutes: number[]
    adchar: null
  }
  geometry: {
    type: 'MultiPolygon' | 'Polygon'
    coordinates: any
  }
}

interface ProjectionFnParamType {
  center: [number, number]
  scale: number
}

interface RadarOption {
  position: THREE.Vector3
  radius: number
  color: string
  opacity: number
  angle: number
  speed: number
}

// Props定义
interface Props {
  initialAdCode?: number
  onRegionClick?: (properties: any) => void
}

const props = withDefaults(defineProps<Props>(), {
  initialAdCode: 100000,
  onRegionClick: () => {}
})

const router = useRouter()

// 返回功能
const goBack = () => {
  try {
    // 在路由跳转前先清理资源
    globalCleanup()
    router.push('/datascreen')
  } catch (error) {
    console.error('返回时清理资源出错:', error)
    // 即使清理出错也要尝试跳转
    router.push('/datascreen')
  }
}

// 地图配置
const mapConfig = {
  mapDepth: 6,
  mapTransparent: true,
  mapOpacity: 0.9,
  mapColor: '#06092A',
  mapHoverColor: '#409EF9',
  mapColorGradient: ['#42A0F9', '#1E6BF8', '#0B388A', '#132354'],
  mapSideColor1: '#3F9FF3',
  mapSideColor2: '#266BF0',
  topLineColor: 0x41c0fb,
  topLineWidth: 3,
  topLineZIndex: 6.5,
  label2dZIndex: 8,
  spotZIndex: 6.2
}

// 地图放大倍率
const MapScale: any = {
  province: 100,
  city: 200,
  district: 300
}

// 雷达配置
const radarData: RadarOption[] = [
  {
    position: new THREE.Vector3(0, 0, 0),
    radius: 50,
    color: '#0A1E70',
    opacity: 0.5,
    angle: Math.PI * 2,
    speed: 2
  },
  {
    position: new THREE.Vector3(0, 0, 0),
    radius: 30,
    color: '#C2C4D6',
    opacity: 0.5,
    angle: Math.PI * 2,
    speed: 2
  }
]

// 响应式数据
const mapRef = ref<HTMLElement>()
const map2dRef = ref<HTMLElement>()
const toolTipRef = ref<HTMLElement>()
const geoJson = ref<GeoJsonType>()
const mapAdCode = ref(props.initialAdCode)
const projectionFnParam = ref<ProjectionFnParamType>({
  center: [104.0, 37.5],
  scale: 40
})

const toolTipData = reactive({
  text: '',
  visible: false,
  x: 0,
  y: 0
})

let lastPick: any = null
let scene: THREE.Scene
let camera: THREE.PerspectiveCamera
let renderer: THREE.WebGLRenderer
let labelRenderer: CSS2DRenderer
let controls: OrbitControls
let animationId: number
let gui: dat.GUI | null = null
let mapObject3D: THREE.Object3D
let diamondConfig: any = { rotationSpeed: 1.0 }
let cleanupFunctions: (() => void)[] = []

// 获取地图数据
const queryMapData = async (code: number) => {
  try {
    const response = await axios.get(
      `https://geo.datav.aliyun.com/areas_v3/bound/${code}_full.json`
    )
    geoJson.value = response.data
  } catch (error) {
    console.error('Failed to load map data:', error)
  }
}

// 初始化场景
const initScene = () => {
  return new THREE.Scene()
}

// 初始化相机
const initCamera = (currentDom: HTMLElement) => {
  const camera = new THREE.PerspectiveCamera(
    30,
    currentDom.clientWidth / currentDom.clientHeight,
    0.1,
    1000
  )
  camera.position.set(-10, -90, 130)
  const cameraHelper = new THREE.CameraHelper(camera)
  return { camera, cameraHelper }
}

// 获取动态地图缩放
const getDynamicMapScale = (mapObject3D: THREE.Object3D, containerRef: HTMLElement) => {
  const width = containerRef.clientWidth
  const height = containerRef.clientHeight
  const refArea = width * height

  const boundingBox = new THREE.Box3().setFromObject(mapObject3D)
  const size = new THREE.Vector3()
  boundingBox.getSize(size)
  
  const scale = Math.round(Math.sqrt(refArea / (size.x * size.y * 400))) + 
    parseFloat((Math.random() + 0.5).toFixed(2))
  return scale
}

// 绘制挤出网格
const drawExtrudeMesh = (point: [number, number][], projectionFn: any) => {
  const shape = new THREE.Shape()
  const pointsArray: number[] = []

  for (let i = 0; i < point.length; i++) {
    const [x, y]: any = projectionFn(point[i])
    if (i === 0) {
      shape.moveTo(x, -y)
    }
    shape.lineTo(x, -y)
    pointsArray.push(x, -y, mapConfig.topLineZIndex)
  }

  const geometry = new THREE.ExtrudeGeometry(shape, {
    depth: mapConfig.mapDepth,
    bevelEnabled: false
  })

  const material = new THREE.MeshPhongMaterial({
    color: mapConfig.mapColorGradient[Math.floor(Math.random() * 4)],
    transparent: mapConfig.mapTransparent,
    opacity: mapConfig.mapOpacity
  })

  const materialSide = new THREE.ShaderMaterial({
    uniforms: {
      color1: { value: new THREE.Color(mapConfig.mapSideColor1) },
      color2: { value: new THREE.Color(mapConfig.mapSideColor2) }
    },
    vertexShader: `
      varying vec3 vPosition;
      void main() {
        vPosition = position;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
      }
    `,
    fragmentShader: `
      uniform vec3 color1;
      uniform vec3 color2;
      varying vec3 vPosition;
      void main() {
        vec3 mixColor = mix(color1, color2, 0.5 - vPosition.z * 0.2);
        gl_FragColor = vec4(mixColor, 1.0);
      }
    `
  })

  const mesh: any = new THREE.Mesh(geometry, [material, materialSide])
  mesh.userData = { isChangeColor: true }

  const lineGeometry = new LineGeometry()
  lineGeometry.setPositions(pointsArray)

  const lineMaterial = new LineMaterial({
    color: mapConfig.topLineColor,
    linewidth: mapConfig.topLineWidth
  })
  lineMaterial.resolution.set(window.innerWidth, window.innerHeight)
  const line = new Line2(lineGeometry, lineMaterial)

  return { mesh, line }
}

// 生成地图3D对象
const generateMapObject3D = (mapdata: GeoJsonType, projectionFnParam: ProjectionFnParamType) => {
  const mapObject3D = new THREE.Object3D()
  const { features: basicFeatures } = mapdata
  const { center, scale } = projectionFnParam

  const projectionFn = d3
    .geoMercator()
    .center(center)
    .scale(scale)
    .translate([0, 0])

  const label2dData: any[] = []

  basicFeatures.forEach((basicFeatureItem: GeoJsonFeature) => {
    const provinceMapObject3D: any = new THREE.Object3D()
    provinceMapObject3D.customProperties = basicFeatureItem.properties

    const featureType = basicFeatureItem.geometry.type
    const featureCoords = basicFeatureItem.geometry.coordinates
    const featureCenterCoord: any = basicFeatureItem.properties.centroid && 
      projectionFn(basicFeatureItem.properties.centroid)
    const featureName: string = basicFeatureItem.properties.name

    if (featureCenterCoord) {
      label2dData.push({
        featureCenterCoord,
        featureName
      })
    }

    if (featureType === 'MultiPolygon') {
      featureCoords.forEach((multiPolygon: [number, number][][]) => {
        multiPolygon.forEach((polygon: [number, number][]) => {
          const { mesh, line } = drawExtrudeMesh(polygon, projectionFn)
          provinceMapObject3D.add(mesh)
          provinceMapObject3D.add(line)
        })
      })
    }

    if (featureType === 'Polygon') {
      featureCoords.forEach((polygon: [number, number][]) => {
        const { mesh, line } = drawExtrudeMesh(polygon, projectionFn)
        provinceMapObject3D.add(mesh)
        provinceMapObject3D.add(line)
      })
    }

    mapObject3D.add(provinceMapObject3D)
  })

  return { mapObject3D, label2dData }
}

// 生成2D标签
const generateMapLabel2D = (label2dData: any[]) => {
  const labelObject2D = new THREE.Object3D()
  label2dData.forEach((item: any) => {
    const { featureCenterCoord, featureName } = item
    const labelObjectItem = draw2dLabel(featureCenterCoord, featureName)
    if (labelObjectItem) {
      labelObject2D.add(labelObjectItem)
    }
  })
  return labelObject2D
}

// 绘制2D标签
const draw2dLabel = (coord: [number, number], provinceName: string) => {
  if (coord && coord.length) {
    const innerHTML = `<div style="color: #fff; pointer-events: none;">${provinceName}</div>`
    const labelDiv = document.createElement('div')
    labelDiv.innerHTML = innerHTML
    labelDiv.style.pointerEvents = 'none'
    const labelObject = new CSS2DObject(labelDiv)
    labelObject.position.set(coord[0], -coord[1], mapConfig.label2dZIndex)
    return labelObject
  }
}

// 生成地图点位
const generateMapSpot = (label2dData: any[]) => {
  const spotObject3D = new THREE.Object3D()
  const spotList: any[] = []
  label2dData.forEach((item: any) => {
    const { featureCenterCoord } = item
    const spotObjectItem = drawSpot(featureCenterCoord)
    if (spotObjectItem && spotObjectItem.circle && spotObjectItem.ring) {
      spotObject3D.add(spotObjectItem.circle)
      spotObject3D.add(spotObjectItem.ring)
      spotList.push(spotObjectItem.ring)
    }
  })
  return { spotObject3D, spotList }
}

// 绘制点位
const drawSpot = (coord: [number, number]) => {
  if (coord && coord.length) {
    const spotGeometry = new THREE.CircleGeometry(0.2, 200)
    const spotMaterial = new THREE.MeshBasicMaterial({
      color: '#3EC5FB',
      side: THREE.DoubleSide
    })
    const circle = new THREE.Mesh(spotGeometry, spotMaterial)
    circle.position.set(coord[0], -coord[1], mapConfig.spotZIndex)

    const ringGeometry = new THREE.RingGeometry(0.2, 0.3, 50)
    const ringMaterial = new THREE.MeshBasicMaterial({
      color: '#3FC5FB',
      side: THREE.DoubleSide,
      transparent: true
    })
    const ring = new THREE.Mesh(ringGeometry, ringMaterial)
    ring.position.set(coord[0], -coord[1], mapConfig.spotZIndex)
    return { circle, ring }
  }
}

// 创建菱形立方体
const createDiamondCube = () => {
  // 创建菱形几何体（八面体）
  const geometry = new THREE.OctahedronGeometry(3, 0) // 半径3，细分0
  
  // 创建发光材质
  const material = new THREE.MeshPhongMaterial({
    color: 0x00d4ff,
    emissive: 0x001122,
    transparent: true,
    opacity: 0.8,
    shininess: 100
  })
  
  const diamondCube = new THREE.Mesh(geometry, material)
  
  // 添加边框
  const edges = new THREE.EdgesGeometry(geometry)
  const lineMaterial = new THREE.LineBasicMaterial({
    color: 0x00ffff,
    transparent: true,
    opacity: 0.9,
    linewidth: 2
  })
  const wireframe = new THREE.LineSegments(edges, lineMaterial)
  diamondCube.add(wireframe)
  
  // 添加旋转动画
  diamondCube.userData.isRotating = true
  
  return diamondCube
}

// 绘制飞行点
const drawflySpot = (curve: any) => {
  const aGeo = new THREE.SphereGeometry(0.3)
  const aMater = new THREE.MeshBasicMaterial({
    color: '#00d4ff', // 改为科技蓝色
    side: THREE.DoubleSide,
    transparent: true,
    opacity: 0.9
  })
  const aMesh: any = new THREE.Mesh(aGeo, aMater)
  aMesh.curve = curve
  aMesh._s = 0
  
  // 添加发光效果
  const glowGeo = new THREE.SphereGeometry(0.5)
  const glowMat = new THREE.MeshBasicMaterial({
    color: '#00d4ff',
    transparent: true,
    opacity: 0.3
  })
  const glowMesh = new THREE.Mesh(glowGeo, glowMat)
  aMesh.add(glowMesh)
  
  return aMesh
}

// 绘制两点连线
const drawLineBetween2Spot = (
  coordStart: [number, number],
  coordEnd: [number, number]
) => {
  const [x0, y0, z0] = [...coordStart, mapConfig.spotZIndex]
  const [x1, y1, z1] = [...coordEnd, mapConfig.spotZIndex]
  
  const curve = new THREE.QuadraticBezierCurve3(
    new THREE.Vector3(x0, -y0, z0),
    new THREE.Vector3((x0 + x1) / 2, -(y0 + y1) / 2, 20),
    new THREE.Vector3(x1, -y1, z1)
  )

  const flySpot = drawflySpot(curve)

  const lineGeometry = new THREE.BufferGeometry()
  const points = curve.getPoints(50)
  const positions: number[] = []
  const colors: number[] = []
  const color = new THREE.Color()

  for (let j = 0; j < points.length; j++) {
    // 创建从蓝色到青色的渐变效果，模拟数据流
    const progress = j / (points.length - 1)
    color.setHSL(0.55 - progress * 0.1, 0.9, 0.5 + progress * 0.3)
    colors.push(color.r, color.g, color.b)
    positions.push(points[j].x, points[j].y, points[j].z)
  }

  lineGeometry.setAttribute(
    'position',
    new THREE.BufferAttribute(new Float32Array(positions), 3, true)
  )
  lineGeometry.setAttribute(
    'color',
    new THREE.BufferAttribute(new Float32Array(colors), 3, true)
  )

  const material = new THREE.LineBasicMaterial({
    vertexColors: true,
    side: THREE.DoubleSide,
    transparent: true,
    opacity: 0.8,
    linewidth: 2
  })
  const flyLine = new THREE.Line(lineGeometry, material)

  return { flyLine, flySpot }
}

// 绘制雷达
const drawRadar = (options: RadarOption, ratio: any) => {
  const { position, radius, color, opacity, speed, angle } = options
  const size = radius * 2
  const plane = new THREE.PlaneGeometry(size, size)
  
  const vertexShader = `
    precision mediump float;
    precision highp int;
    varying vec2 vPosition;
    void main () {
        vPosition = vec2(position.x, position.y);
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }`

  const fragmentShader = `
    precision mediump float;
    precision highp int;
    uniform float uTime;
    uniform float u_radius;
    uniform float u_speed;
    uniform float u_opacity;
    uniform float u_width;
    uniform vec3 u_color;
    varying vec2 vPosition;
    #define PI 3.14159265359
    void main () {
        float currentRadius = u_speed * uTime;
        float angle = atan(vPosition.y, vPosition.x) + PI;
        float angleT = mod(currentRadius + angle, PI * 2.0);
        float dist = distance(vec2(0.0, 0.0), vPosition);
        float tempOpacity = 0.0;
        float circleWidth = 5.0;
        if (dist < u_radius && dist > u_radius - circleWidth) {
            float pct = smoothstep(u_radius - circleWidth, u_radius, dist);
            tempOpacity = sin(pct * PI);
        }
        if (dist < (u_radius - 5.0)) {
            tempOpacity = 1.0 - angleT / u_width;
        }
        gl_FragColor = vec4(u_color, u_opacity * tempOpacity);
    }`

  const material = new THREE.ShaderMaterial({
    transparent: true,
    depthWrite: false,
    side: THREE.DoubleSide,
    uniforms: {
      uTime: ratio,
      u_radius: { value: radius },
      u_speed: { value: speed },
      u_opacity: { value: opacity },
      u_width: { value: angle },
      u_color: { value: new THREE.Color(color) }
    },
    vertexShader,
    fragmentShader
  })
  
  const planeMesh = new THREE.Mesh(plane, material)
  planeMesh.position.copy(position)
  return planeMesh
}

// 双击事件处理
const dblClickFn = (customProperties: any) => {
  mapAdCode.value = customProperties.adcode
  projectionFnParam.value = {
    center: customProperties.centroid,
    scale: MapScale[customProperties.level]
  }
  props.onRegionClick?.(customProperties)
}

// 初始化3D场景
const init3DScene = async () => {
  try {
    if (!mapRef.value || !map2dRef.value) {
      console.warn('DOM元素未准备就绪')
      return
    }

    const currentDom = mapRef.value
    const ratio = { value: 0 }

  // 初始化场景
  scene = initScene()

  // 初始化相机
  const { camera: cam, cameraHelper } = initCamera(currentDom)
  camera = cam

  // 初始化渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true })
  renderer.setSize(currentDom.clientWidth, currentDom.clientHeight)
  
  if (currentDom.childNodes[0]) {
    currentDom.removeChild(currentDom.childNodes[0])
  }
  currentDom.appendChild(renderer.domElement)

  // CSS2D渲染器
  labelRenderer = new CSS2DRenderer()
  labelRenderer.setSize(currentDom.clientWidth, currentDom.clientHeight)
  labelRenderer.domElement.style.position = 'absolute'
  labelRenderer.domElement.style.top = '0px'
  
  const labelRendererDom = map2dRef.value
  if (labelRendererDom?.childNodes[0]) {
    labelRendererDom.removeChild(labelRendererDom.childNodes[0])
  }
  labelRendererDom.appendChild(labelRenderer.domElement)

  if (!geoJson.value) return

  // 生成地图3D模型
  const mapData = generateMapObject3D(
    geoJson.value,
    projectionFnParam.value
  )
  mapObject3D = mapData.mapObject3D
  const label2dData = mapData.label2dData
  scene.add(mapObject3D)

  // 动态地图缩放
  const mapScale = getDynamicMapScale(mapObject3D, currentDom)

  // 生成2D标签
  const labelObject2D = generateMapLabel2D(label2dData)
  mapObject3D.add(labelObject2D)

  // 生成点位
  const { spotList, spotObject3D } = generateMapSpot(label2dData)
  mapObject3D.add(spotObject3D)

  // 加载3D模型
  const modelObject3D = new THREE.Object3D()
  let modelMixer: any[] = []
  const loader = new GLTFLoader()
  const dracoLoader = new DRACOLoader()
  dracoLoader.setDecoderPath('/draco/')
  loader.setDRACOLoader(dracoLoader)

  loader.load('/models/cone.glb', (glb) => {
    label2dData.forEach((item: any) => {
      const { featureCenterCoord } = item
      const clonedModel = glb.scene.clone()
      const mixer = new THREE.AnimationMixer(clonedModel)
      const clonedAnimations = glb.animations.map((clip) => clip.clone())
      
      clonedAnimations.forEach((clip) => {
        mixer.clipAction(clip).play()
      })

      modelMixer.push(mixer)

      clonedModel.position.set(
        featureCenterCoord[0],
        -featureCenterCoord[1],
        mapConfig.spotZIndex
      )
      clonedModel.scale.set(0.3, 0.3, 0.6)
      modelObject3D.add(clonedModel)
    })

    mapObject3D.add(modelObject3D)
  })

  // 生成连线 - 以四川为中心向其他省份传输
  const connectLine: any[] = []
  
  // 查找四川省的索引
  let sichuanIndex = -1
  label2dData.forEach((item, index) => {
    if (item.featureName.includes('四川') || item.featureName.includes('川')) {
      sichuanIndex = index
    }
  })
  
  console.log('四川省索引:', sichuanIndex, '省份名称:', label2dData[sichuanIndex]?.featureName)
  
  // 如果找到四川省，创建从四川到其他省份的连接线
  if (sichuanIndex !== -1) {
    // 选择一些主要省份作为目标
    const targetProvinces = ['北京', '上海', '广东', '江苏', '浙江', '山东', '河南', '湖北', '湖南', '陕西', '云南', '贵州']
    
    label2dData.forEach((item, index) => {
      if (index !== sichuanIndex) {
        // 检查是否是目标省份之一
        const isTargetProvince = targetProvinces.some(province => 
          item.featureName.includes(province) || item.featureName.includes(province.replace('省', ''))
        )
        
        if (isTargetProvince) {
          connectLine.push({ indexStart: sichuanIndex, indexEnd: index })
          console.log('添加连接线:', label2dData[sichuanIndex].featureName, '->', item.featureName)
        }
      }
    })
  } else {
    // 如果没找到四川省，使用备用方案
    console.warn('未找到四川省，使用备用连接方案')
    const centerIndex = Math.floor(label2dData.length / 2)
    for (let i = 0; i < Math.min(8, label2dData.length - 1); i++) {
      if (i !== centerIndex) {
        connectLine.push({ indexStart: centerIndex, indexEnd: i })
      }
    }
  }

  const flyObject3D = new THREE.Object3D()
  const flySpotList: any[] = []
  connectLine.forEach((item: any) => {
    const { indexStart, indexEnd } = item
    const { flyLine, flySpot } = drawLineBetween2Spot(
      label2dData[indexStart].featureCenterCoord,
      label2dData[indexEnd].featureCenterCoord
    )
    flyObject3D.add(flyLine)
    flyObject3D.add(flySpot)
    flySpotList.push(flySpot)
  })
  mapObject3D.add(flyObject3D)

  // 在四川省上方添加菱形立方体
  if (sichuanIndex !== -1) {
    const sichuanCoord = label2dData[sichuanIndex].featureCenterCoord
    const diamondCube = createDiamondCube()
    diamondCube.position.set(sichuanCoord[0], -sichuanCoord[1], 8) // 高度设为8，比较低
    mapObject3D.add(diamondCube)
    console.log('在四川省添加菱形立方体:', sichuanCoord)
  }

  // 绘制雷达
  radarData.forEach((item: RadarOption) => {
    const planeMesh = drawRadar(item, ratio)
    scene.add(planeMesh)
  })

  // 添加辅助对象
  scene.add(cameraHelper)
  const axesHelper = new THREE.AxesHelper(100)
  scene.add(axesHelper)

  // 初始化控制器
  controls = new OrbitControls(camera, labelRenderer.domElement)

  // 添加光源
  const light = new THREE.PointLight(0xffffff, 1.5)
  light.position.set(0, -5, 30)
  scene.add(light)

  const lightHelper = new THREE.PointLightHelper(light)
 // scene.add(lightHelper)

  // 射线检测
  const raycaster = new THREE.Raycaster()
  const pointer = new THREE.Vector2()

  // 鼠标移动事件
  const onMouseMove = (e: MouseEvent) => {
    const rect = currentDom.getBoundingClientRect()
    pointer.x = ((e.clientX - rect.left) / currentDom.clientWidth) * 2 - 1
    pointer.y = -((e.clientY - rect.top) / currentDom.clientHeight) * 2 + 1

    const intersects = raycaster.intersectObjects(scene.children, true)

    // 调试信息
    if (intersects.length > 0) {
      console.log('射线检测到对象:', intersects.length, '个')
      console.log('第一个对象:', intersects[0].object.type, intersects[0].object.userData)
    }

    if (lastPick) {
      const color = mapConfig.mapColorGradient[Math.floor(Math.random() * 4)]
      if (lastPick.object.material && lastPick.object.material[0]) {
        lastPick.object.material[0].color.set(color)
        lastPick.object.material[0].opacity = mapConfig.mapOpacity
      }
    }
    lastPick = null

    lastPick = intersects.find((item: any) => item.object.userData.isChangeColor)

    if (lastPick) {
      // 获取父对象的属性
      const properties = lastPick.object.parent?.customProperties
      
      if (lastPick.object.material && lastPick.object.material[0]) {
        lastPick.object.material[0].color.set(mapConfig.mapHoverColor)
        lastPick.object.material[0].opacity = 1
      }

      // 设置工具提示
      toolTipData.x = e.clientX + 2
      toolTipData.y = e.clientY + 2
      toolTipData.visible = true
      
      // 确保有属性信息
      if (properties && properties.name) {
        toolTipData.text = properties.name
      } else {
        toolTipData.text = '未知区域'
      }
      
      console.log('Hover检测到:', properties?.name || '未知区域')
    } else {
      toolTipData.visible = false
    }
  }

  // 双击事件
  const onDblClick = () => {
    const intersects = raycaster.intersectObjects(scene.children, true)
    const target = intersects.find((item: any) => item.object.userData.isChangeColor)
    if (target) {
      const obj: any = target.object.parent
      const p = obj.customProperties
      dblClickFn(p)
    }
  }

  // 窗口大小调整
  const onResize = () => {
    camera.aspect = currentDom.clientWidth / currentDom.clientHeight
    camera.updateProjectionMatrix()
    renderer.setSize(currentDom.clientWidth, currentDom.clientHeight)
    labelRenderer.setSize(currentDom.clientWidth, currentDom.clientHeight)
    renderer.setPixelRatio(window.devicePixelRatio)
  }

  // 动画
  gsap.to(mapObject3D.scale, { x: mapScale, y: mapScale, z: 1, duration: 1 })

  // 渲染循环
  const clock = new THREE.Clock()
  const animate = () => {
    const delta = clock.getDelta()
    modelMixer.forEach((mixer: any) => mixer.update(delta))

    ratio.value += 0.01

    animationId = requestAnimationFrame(animate)
    raycaster.setFromCamera(pointer, camera)
    renderer.render(scene, camera)
    labelRenderer.render(scene, camera)

    // 圆环动画
    spotList.forEach((mesh: any) => {
      mesh._s += 0.01
      mesh.scale.set(1 * mesh._s, 1 * mesh._s, 1 * mesh._s)
      if (mesh._s <= 2) {
        mesh.material.opacity = 2 - mesh._s
      } else {
        mesh._s = 1
      }
    })

    // 飞行点动画
    flySpotList.forEach((mesh: any) => {
      mesh._s += 0.003
      const tankPosition = mesh.curve.getPointAt(mesh._s % 1)
      mesh.position.set(tankPosition.x, tankPosition.y, tankPosition.z)
    })

    // 菱形立方体旋转动画
    if (mapObject3D) {
      mapObject3D.traverse((child: any) => {
        if (child.userData.isRotating) {
          const speed = diamondConfig.rotationSpeed * 0.01
          child.rotation.x += speed
          child.rotation.y += speed * 1.5
          child.rotation.z += speed * 0.8
        }
      })
    }
  }

  animate()

  // 添加事件监听
  window.addEventListener('resize', onResize)
  currentDom.addEventListener('mousemove', onMouseMove)
  currentDom.addEventListener('dblclick', onDblClick)

  // dat.GUI配置 - 先清理已存在的GUI
  if (gui) {
    try {
      if (gui.domElement && gui.domElement.parentNode) {
        gui.domElement.parentNode.removeChild(gui.domElement)
      }
      gui.destroy()
    } catch (error) {
      console.warn('清理旧GUI时出错:', error)
    }
    gui = null
  }
  
  gui = new dat.GUI()
  gui.width = 300
  
  // 确保GUI在最顶层显示并可交互
  const guiDom = gui.domElement
  guiDom.style.position = 'fixed'
  guiDom.style.top = '10px'
  guiDom.style.right = '10px'
  guiDom.style.zIndex = '99999'
  guiDom.style.pointerEvents = 'auto'
  
  // 确保GUI容器不被其他元素遮挡
  document.body.appendChild(guiDom)
  
  const colorConfig = {
    mapColor: mapConfig.mapColor,
    mapHoverColor: mapConfig.mapHoverColor,
    mapSideColor1: mapConfig.mapSideColor1,
    mapSideColor2: mapConfig.mapSideColor2,
    topLineColor: `#${mapConfig.topLineColor.toString(16)}`
  }

  gui.addColor(colorConfig, 'mapColor').name('地图颜色').onChange((value: string) => {
    console.log('地图颜色改变:', value)
    mapConfig.mapColor = value
    if (mapObject3D) {
      mapObject3D.traverse((obj: any) => {
        if (obj.material && obj.material[0] && obj.userData.isChangeColor) {
          obj.material[0].color.set(value)
        }
      })
    }
  })

  gui.addColor(colorConfig, 'mapHoverColor').name('地图Hover颜色').onChange((value: string) => {
    console.log('Hover颜色改变:', value)
    mapConfig.mapHoverColor = value
  })

  // 地图透明度控制
  const opacityConfig = { opacity: mapConfig.mapOpacity }
  gui.add(opacityConfig, 'opacity', 0, 1).name('地图透明度').onChange((v: number) => {
    console.log('透明度改变:', v)
    mapConfig.mapOpacity = v
    if (mapObject3D) {
      mapObject3D.traverse((obj: any) => {
        if (obj.material && obj.material[0] && obj.userData.isChangeColor) {
          obj.material[0].opacity = v
        }
      })
    }
  })

  // 地图深度控制
  const depthConfig = { depth: mapConfig.mapDepth }
  gui.add(depthConfig, 'depth', 1, 20).name('地图深度').onChange((v: number) => {
    mapConfig.mapDepth = v
    // 这里可以重新生成地图以应用新的深度
  })

  const helperConfig = {
    cameraHelper: true,
    axesHelper: true,
    lightHelper: true
  }

  // 菱形立方体控制
  diamondConfig = {
    visible: true,
    rotationSpeed: 1.0,
    height: 8
  }
  
  gui.add(diamondConfig, 'visible').name('显示菱形立方体').onChange((v: boolean) => {
    if (mapObject3D) {
      mapObject3D.traverse((child: any) => {
        if (child.userData.isRotating) {
          child.visible = v
        }
      })
    }
  })
  
  gui.add(diamondConfig, 'rotationSpeed', 0, 3).name('旋转速度').onChange((v: number) => {
    // 旋转速度会在动画循环中使用
  })
  
  gui.add(diamondConfig, 'height', 5, 20).name('立方体高度').onChange((v: number) => {
    if (mapObject3D) {
      mapObject3D.traverse((child: any) => {
        if (child.userData.isRotating) {
          const sichuanCoord = label2dData[sichuanIndex].featureCenterCoord
          child.position.z = v
        }
      })
    }
  })

  gui.add(helperConfig, 'cameraHelper').name('显示CameraHelper').onChange((v: boolean) => {
    console.log('CameraHelper显示状态:', v)
    if (v) {
      scene.add(cameraHelper)
    } else {
      scene.remove(cameraHelper)
    }
  })

  // 获取场景中的点光源
  const lights = scene.children.filter(child => child instanceof THREE.PointLight) as THREE.PointLight[]
  if (lights.length > 0) {
    const light = lights[0]
    const lightConfig = { intensity: light.intensity }
    gui.add(lightConfig, 'intensity', 0, 5).name('光强度').onChange((v: number) => {
      console.log('光强度改变:', v)
      light.intensity = v
    })
  }



  // 创建清理函数
  const cleanup = () => {
    try {
      // 移除事件监听器
      window.removeEventListener('resize', onResize)
      currentDom.removeEventListener('mousemove', onMouseMove)
      currentDom.removeEventListener('dblclick', onDblClick)
      
      // 停止动画循环
      if (animationId) {
        cancelAnimationFrame(animationId)
        animationId = 0
      }
      
      // 清理GUI
      if (gui) {
        try {
          if (gui.domElement && gui.domElement.parentNode) {
            gui.domElement.parentNode.removeChild(gui.domElement)
          }
          gui.destroy()
        } catch (error) {
          console.warn('清理GUI时出错:', error)
        }
        gui = null
      }
      
      // 清理Three.js资源
      if (scene) {
        scene.traverse((child) => {
          if (child instanceof THREE.Mesh) {
            if (child.geometry) {
              child.geometry.dispose()
            }
            if (child.material) {
              if (Array.isArray(child.material)) {
                child.material.forEach(material => material.dispose())
              } else {
                child.material.dispose()
              }
            }
          }
        })
        scene.clear()
      }
      
      // 清理渲染器
      if (renderer) {
        renderer.dispose()
        if (renderer.domElement && renderer.domElement.parentNode) {
          renderer.domElement.parentNode.removeChild(renderer.domElement)
        }
      }
      
      // 清理CSS2D渲染器
      if (labelRenderer) {
        if (labelRenderer.domElement && labelRenderer.domElement.parentNode) {
          labelRenderer.domElement.parentNode.removeChild(labelRenderer.domElement)
        }
      }
      
      // 清理控制器
      if (controls) {
        controls.dispose()
      }
      
      // 执行其他清理函数
      cleanupFunctions.forEach(fn => {
        try {
          fn()
        } catch (error) {
          console.warn('执行清理函数时出错:', error)
        }
      })
      cleanupFunctions = []
      
    } catch (error) {
      console.error('清理3D场景时出错:', error)
    }
  }
  
  // 将清理函数添加到清理函数列表
  cleanupFunctions.push(cleanup)
  
  return cleanup
  
  } catch (error) {
    console.error('初始化3D场景时出错:', error)
    // 出错时也要尝试清理已创建的资源
    try {
      globalCleanup()
    } catch (cleanupError) {
      console.error('清理失败的初始化资源时出错:', cleanupError)
    }
  }
}

// 防止重复初始化的标志
let isInitialized = false

// 监听地图数据变化
watch(geoJson, (newGeoJson) => {
  if (newGeoJson && !isInitialized) {
    isInitialized = true
    init3DScene()
  }
})

// 监听地区代码变化
watch(mapAdCode, (newCode) => {
  // 先清理现有场景
  if (isInitialized) {
    globalCleanup()
    isInitialized = false
  }
  queryMapData(newCode)
})

// 组件挂载
onMounted(() => {
  queryMapData(mapAdCode.value)
})

// 全局清理函数
const globalCleanup = () => {
  try {
    // 停止动画循环
    if (animationId) {
      cancelAnimationFrame(animationId)
      animationId = 0
    }
    
    // 清理GUI
    if (gui) {
      try {
        if (gui.domElement && gui.domElement.parentNode) {
          gui.domElement.parentNode.removeChild(gui.domElement)
        }
        gui.destroy()
      } catch (error) {
        console.warn('全局清理GUI时出错:', error)
      }
      gui = null
    }
    
    // 执行所有清理函数
    cleanupFunctions.forEach(fn => {
      try {
        fn()
      } catch (error) {
        console.warn('执行全局清理函数时出错:', error)
      }
    })
    cleanupFunctions = []
    
  } catch (error) {
    console.error('全局清理时出错:', error)
  }
}

// 组件卸载
onUnmounted(() => {
  globalCleanup()
})

// 暴露方法给父组件
defineExpose({
  queryMapData,
  setMapAdCode: (code: number) => {
    mapAdCode.value = code
  }
})
</script>

<style scoped>
.china-map-3d-container {
  width: 100%;
  height: 100vh;
  overflow: hidden;
  position: relative;
  background: linear-gradient(135deg, #0a0e27 0%, #1a1f3a 25%, #2d3561 50%, #1a1f3a 75%, #0a0e27 100%);
}

/* 返回按钮 */
.back-button {
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 9998;
  background: linear-gradient(135deg, rgba(0, 212, 255, 0.8), rgba(0, 150, 255, 0.9));
  border: 2px solid #00d4ff;
  border-radius: 8px;
  color: #ffffff;
  padding: 10px 20px;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 8px;
  transition: all 0.3s ease;
  backdrop-filter: blur(10px);
  box-shadow: 0 4px 15px rgba(0, 212, 255, 0.3);
}

.back-button:hover {
  background: linear-gradient(135deg, rgba(0, 212, 255, 1), rgba(0, 150, 255, 1));
  border-color: #00f4ff;
  box-shadow: 0 6px 20px rgba(0, 212, 255, 0.6);
  transform: translateY(-2px);
}

.back-icon {
  font-size: 18px;
  font-weight: bold;
}

.back-text {
  font-size: 14px;
}

/* 标题区域 */
.title-section {
  position: absolute;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 9998;
  text-align: center;
}

.main-title {
  color: #ffffff;
  font-size: 28px;
  font-weight: bold;
  margin: 0;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
  background: linear-gradient(45deg, #00d4ff, #00ff88);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.sub-title {
  color: #a0a0a0;
  font-size: 14px;
  margin: 5px 0 0 0;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}

.map-2d-layer {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
}

.map-3d-layer {
  width: 100%;
  height: 100%;
}

.tooltip {
  position: fixed;
  z-index: 99998;
  background: rgba(1, 2, 9, 0.95);
  min-width: 80px;
  max-width: 200px;
  height: auto;
  padding: 8px 12px;
  border: 2px solid #00d4ff;
  border-radius: 6px;
  color: #ffffff;
  font-size: 14px;
  font-weight: 600;
  pointer-events: none;
  visibility: hidden;
  backdrop-filter: blur(10px);
  box-shadow: 0 4px 15px rgba(0, 212, 255, 0.6);
  white-space: nowrap;
  transition: opacity 0.2s ease;
}

.tooltip.visible {
  visibility: visible;
  opacity: 1;
}
</style>
